using System;
using System.Threading;
using Oracle.ManagedDataAccess.Client;
using OracleInternal.Common;

namespace OracleInternal.NotificationServices
{
	internal class NotificationQueue
	{
		private ONS ons;

		private QueueElement head;

		private QueueElement tail;

		private object lock_Renamed;

		private object closelock;

		private int waiters_Renamed_Field;

		private int count_Renamed_Field;

		private bool closed;

		private bool closing;

		private int closewaiters;

		protected internal const int DEFAULT_PRIORITY = 10;

		protected internal static readonly int LOW_PRIORITY = 10;

		protected internal const int HIGH_PRIORITY = 1;

		internal NotificationQueue(ONS myONS)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.NotificationQueue, OracleTraceFuncName.ctor);
			}
			ons = myONS;
			head = null;
			tail = null;
			waiters_Renamed_Field = 0;
			count_Renamed_Field = 0;
			lock_Renamed = new object();
			closed = false;
			closelock = null;
			closewaiters = 0;
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.NotificationQueue, OracleTraceFuncName.ctor);
			}
		}

		protected internal virtual void enqueue(object e)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.NotificationQueue, OracleTraceFuncName.enqueue);
			}
			try
			{
				QueueElement next = new QueueElement(e);
				lock (lock_Renamed)
				{
					if (!closed && !closing)
					{
						if (head == null)
						{
							head = next;
						}
						else if (tail == null)
						{
							head.next = (tail = next);
						}
						else
						{
							tail.next = next;
							tail = next;
						}
						if (waiters_Renamed_Field > 0)
						{
							Monitor.Pulse(lock_Renamed);
							waiters_Renamed_Field--;
						}
						count_Renamed_Field++;
					}
				}
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.NotificationQueue, OracleTraceFuncName.enqueue, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.NotificationQueue, OracleTraceFuncName.enqueue);
				}
			}
		}

		protected internal virtual void push(object e, int p)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.NotificationQueue, OracleTraceFuncName.push);
			}
			try
			{
				QueueElement queueElement = new QueueElement(e, p);
				lock (lock_Renamed)
				{
					if (closed || closing)
					{
						return;
					}
					if (head == null)
					{
						head = queueElement;
					}
					else if (p <= head.priority)
					{
						if (tail == null)
						{
							tail = head;
						}
						queueElement.next = head;
						head = queueElement;
					}
					else
					{
						QueueElement queueElement2 = head;
						QueueElement next = head.next;
						while (next != null && p > next.priority)
						{
							queueElement2 = next;
							next = next.next;
						}
						if (next != null)
						{
							queueElement2.next = queueElement;
							queueElement.next = next;
						}
						else
						{
							queueElement2.next = queueElement;
							tail = queueElement;
						}
					}
					if (waiters_Renamed_Field > 0)
					{
						Monitor.Pulse(lock_Renamed);
						waiters_Renamed_Field--;
					}
					count_Renamed_Field++;
				}
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.NotificationQueue, OracleTraceFuncName.push, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.NotificationQueue, OracleTraceFuncName.push);
				}
			}
		}

		protected internal virtual void close()
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.NotificationQueue, OracleTraceFuncName.close);
			}
			lock (lock_Renamed)
			{
				closed = true;
				if (waiters_Renamed_Field > 0)
				{
					Monitor.PulseAll(lock_Renamed);
				}
			}
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.NotificationQueue, OracleTraceFuncName.close);
			}
		}

		protected internal virtual object dequeue(bool blocking)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.NotificationQueue, OracleTraceFuncName.dequeue);
			}
			try
			{
				return internalDequeue(blocking, -1L);
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.NotificationQueue, OracleTraceFuncName.dequeue, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.NotificationQueue, OracleTraceFuncName.dequeue);
				}
			}
		}

		private object internalDequeue(bool blocking, long wait)
		{
			object obj = null;
			bool flag = false;
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.NotificationQueue, OracleTraceFuncName.internalDequeue);
			}
			try
			{
				lock (lock_Renamed)
				{
					flag = closing;
					if (!closed)
					{
						if (blocking && head == null && !closing)
						{
							waiters_Renamed_Field++;
							try
							{
								if (wait != -1)
								{
									Monitor.Wait(lock_Renamed, TimeSpan.FromMilliseconds(wait));
								}
								else
								{
									Monitor.Wait(lock_Renamed);
								}
							}
							catch (Exception)
							{
							}
						}
						if (head != null)
						{
							obj = head.obj;
							if (head.next == tail)
							{
								tail = null;
							}
							head = head.next;
							count_Renamed_Field--;
						}
					}
				}
				if (obj == null && flag)
				{
					lock (closelock)
					{
						if (closewaiters > 0)
						{
							Monitor.PulseAll(closelock);
						}
					}
				}
				return obj;
			}
			catch (Exception ex2)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.NotificationQueue, OracleTraceFuncName.internalDequeue, ex2);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.NotificationQueue, OracleTraceFuncName.internalDequeue);
				}
			}
		}

		protected internal virtual void wake()
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.NotificationQueue, OracleTraceFuncName.wake);
			}
			lock (lock_Renamed)
			{
				if (waiters_Renamed_Field > 0)
				{
					Monitor.PulseAll(lock_Renamed);
				}
			}
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.NotificationQueue, OracleTraceFuncName.wake);
			}
		}

		protected internal virtual void drain_and_close(long timeout)
		{
			bool flag = false;
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.NotificationQueue, OracleTraceFuncName.drain_and_close);
			}
			try
			{
				lock (lock_Renamed)
				{
					closing = true;
					closelock = new object();
					if (count_Renamed_Field > 0)
					{
						flag = true;
					}
				}
				if (flag)
				{
					lock (closelock)
					{
						lock (lock_Renamed)
						{
							if (count_Renamed_Field == 0)
							{
								flag = false;
							}
						}
						if (flag)
						{
							try
							{
								closewaiters++;
								Monitor.Wait(closelock, TimeSpan.FromMilliseconds(timeout));
							}
							catch (Exception ex)
							{
								OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.NotificationQueue, OracleTraceFuncName.drain_and_close, ex);
							}
							finally
							{
								closewaiters--;
							}
						}
					}
				}
				close();
			}
			catch (Exception ex2)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.NotificationQueue, OracleTraceFuncName.drain_and_close, ex2);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.NotificationQueue, OracleTraceFuncName.drain_and_close);
				}
			}
		}
	}
}
